package plugin

import (
	"context"
	"net/http"

	"gitee.com/mkwchecking/k-scaffold/apps/register"
	"gitee.com/mkwchecking/k-scaffold/config"
	"gitee.com/mkwchecking/k-scaffold/pkg/rely/ctx"
	"gitee.com/mkwchecking/k-scaffold/pkg/rely/gin"
	klog "gitee.com/mkwchecking/k-scaffold/pkg/rely/log/kratos"
	"github.com/go-kratos/kratos/v2/transport"
	khttp "github.com/go-kratos/kratos/v2/transport/http"
)

func (p *Plugins) GetHttpEngine() (http.Handler, error) {
	if p._httpEngine != nil {
		return p._httpEngine, nil
	}

	p._httpEngine = gin.NewGin()
	return p._httpEngine, nil
}

func (p *Plugins) HttpContext() (context.Context, error) {
	c := p.Ctx()

	if log, err := p.GetLogger(); err != nil {
		return nil, err
	} else {
		c = context.WithValue(c, ctx.LoggerKey{}, log)
	}

	if gdb, err := p.GetGdb(); err != nil {
		return nil, err
	} else {
		c = context.WithValue(c, ctx.GormKey{}, gdb)
	}

	if trace, err := p.GetTrace(); err != nil {
		return nil, err
	} else {
		c = context.WithValue(c, ctx.TraceKey{}, trace)
	}

	if casbin, err := p.GetCasbin(); err != nil {
		return nil, err
	} else {
		c = context.WithValue(c, ctx.CasbinKey{}, casbin)
	}

	if redis, err := p.GetRedis(); err != nil {
		return nil, err
	} else {
		c = context.WithValue(c, ctx.RedisKey{}, redis)
	}

	return c, nil
}

func (p *Plugins) GetHttpServer() (transport.Server, error) {
	if p._httpSvr != nil {
		return p._httpSvr, nil
	}

	httpConf, err := config.GetHTTPServer()
	if err != nil {
		return nil, err
	}

	logger, err := p.GetLogger()

	if err != nil {
		return nil, err
	}

	srv := khttp.NewServer(
		khttp.Address(httpConf.Addr),
		khttp.Middleware(register.GetAppsMiddleware()...),
		khttp.Network(httpConf.Network),
		khttp.Logger(klog.NewLogger(logger.Logger)),
		khttp.Timeout(httpConf.Timeout),
	)

	httpHandler, err := p.GetHttpEngine()
	if err != nil {
		return nil, err
	}

	httpCtx, err := p.HttpContext()
	if err != nil {
		return nil, err
	}

	apps := register.GetApps()
	for _, app := range apps {
		if httpApp, ok := app.(register.IHttpRouter); ok {
			if err := httpApp.InstallHttpRouter(httpCtx, srv, httpHandler); err != nil {
				return nil, err
			}
		}
	}

	srv.Handler = httpHandler

	p._httpSvr = srv
	return p._httpSvr, nil
}
